using Dapper;
using MediatR;
using Microsoft.Extensions.Logging;
using RBAC.Domain.Dto.Output;
using RBAC.Domain.PurchasingManagement.PurchaseOrders;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Read.Api.Application.Command.ERP.PurchasingManagement.PurchaseOrders;
using RBAC.Read.Api.Application.Dto.ERP;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace RBAC.Read.Api.Application.Handler.ERP.PurchasingManagement.PurchaseOrders
{
    /// <summary>
    /// 采购订单主表列表查询（分页 + 条件）
    /// </summary>
    public class GetPurchaseOrdersListHandler : IRequestHandler<GetPurchaseOrdersListCommand, APIPaging<PurchaseOrderListDto>>
    {
        private readonly IBaseRepository<PurchaseOrderInfo> _repo;
        private readonly ILogger<GetPurchaseOrdersListHandler> _logger;

        public GetPurchaseOrdersListHandler(IBaseRepository<PurchaseOrderInfo> repo,
            ILogger<GetPurchaseOrdersListHandler> logger)
        {
            _repo = repo;
            _logger = logger;
        }

        public Task<APIPaging<PurchaseOrderListDto>> Handle(GetPurchaseOrdersListCommand request, CancellationToken cancellationToken)
        {
            var res = new APIPaging<PurchaseOrderListDto>();
            try
            {
                var fromSql = " FROM PurchaseOrderInfo p WHERE p.IsDeleted = 0";
                var whereParts = new List<string>();
                var param = new DynamicParameters();

                if (!string.IsNullOrWhiteSpace(request.DocCode))
                {
                    whereParts.Add("p.DocCode LIKE @DocCode");
                    param.Add("DocCode", $"%{request.DocCode}%");
                }
                if (!string.IsNullOrWhiteSpace(request.docStatus))
                {
                    whereParts.Add("p.docStatus = @docStatus");
                    param.Add("docStatus", request.docStatus);
                }
                if (!string.IsNullOrWhiteSpace(request.bizStatus))
                {
                    whereParts.Add("p.bizStatus = @bizStatus");
                    param.Add("bizStatus", request.bizStatus);
                }
                if (!string.IsNullOrWhiteSpace(request.BizType))
                {
                    whereParts.Add("p.BizType = @BizType");
                    param.Add("BizType", request.BizType);
                }
                if (!string.IsNullOrWhiteSpace(request.purchaseDept))
                {
                    whereParts.Add("p.purchaseDept = @purchaseDept");
                    param.Add("purchaseDept", request.purchaseDept);
                }
                if (!string.IsNullOrWhiteSpace(request.purchaser))
                {
                    whereParts.Add("p.purchaser = @purchaser");
                    param.Add("purchaser", request.purchaser);
                }
                if (request.DocDateStart.HasValue)
                {
                    whereParts.Add("p.docDate >= @DocDateStart");
                    param.Add("DocDateStart", request.DocDateStart.Value.Date);
                }
                if (request.DocDateEnd.HasValue)
                {
                    whereParts.Add("p.docDate < @DocDateEnd");
                    param.Add("DocDateEnd", request.DocDateEnd.Value.Date.AddDays(1));
                }

                var whereSql = whereParts.Count > 0 ? (" AND " + string.Join(" AND ", whereParts)) : string.Empty;

                var countSql = "SELECT COUNT(1)" + fromSql + whereSql;
                var total = _repo.Query<int>(countSql, param).FirstOrDefault();

                res.Code = APIEnums.Success;
                res.TotalCount = total;

                if (total == 0)
                {
                    res.PageDatas = new List<PurchaseOrderListDto>();
                    res.Msg = "获取采购订单列表成功";
                    return Task.FromResult(res);
                }

                var offset = (request.PageIndex - 1) * request.PageSize;
                if (offset < 0) offset = 0;
                param.Add("Offset", offset);
                param.Add("PageSize", request.PageSize);

                var dataSql = @"SELECT 
                                    p.Id,
                                    p.DocCode,
                                    p.docDate,
                                    p.docStatus,
                                    p.BizType,
                                    p.purchaseDept,
                                    p.purchaser,
                                    p.bizStatus,
                                    p.arrivalDate,
                                    p.auditDate,
                                    p.Operatorer,
                                    p.supplierId,
                                    p.docType,
                                    p.contractUpload,
                                    p.materialDemand,
                                    p.contractNo,
                                    p.remark,
                                    IFNULL(agg.unitPrice, 0) AS unitPrice,
                                    IFNULL(agg.amount, 0) AS amount
                                FROM PurchaseOrderInfo p
                                LEFT JOIN (
                                    SELECT 
                                        PurchaseOrderId,
                                        SUM(amount) AS amount,
                                        CASE WHEN SUM(qty) = 0 THEN 0 ELSE SUM(amount) / SUM(qty) END AS unitPrice
                                    FROM PurchasingMaterialInfo
                                    WHERE IsDel = 0
                                    GROUP BY PurchaseOrderId
                                ) agg ON agg.PurchaseOrderId = p.Id
                                WHERE p.IsDeleted = 0" + whereSql + @"
                                ORDER BY p.Id DESC
                                LIMIT @Offset, @PageSize";

                var rows = _repo.Query<PurchaseOrderListDto>(dataSql, param).ToList();
                res.PageDatas = rows;
                res.Msg = "获取采购订单列表成功";
            }
            catch (Exception ex)
            {
                res.Code = APIEnums.Error;
                res.Msg = "获取采购订单列表失败";
                _logger.LogError(ex, "获取采购订单列表失败: {Message}", ex.Message);
            }

            return Task.FromResult(res);
        }
    }
}
